From 280e2b125899cbdf268cf24c582a31068ca81a02 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 10:36:47 +0000 Subject: [PATCH] ioemu: Support the WMVi pseudoencoding in the vnc server. If the client implements it, it is supposed to be able to change colour depth when receiving a WMVi message. Signed-off-by: Stefano Stabellini --- tools/ioemu/vl.c | 9 ---- tools/ioemu/vnc.c | 106 +++++++++++++++++++++++++++++----------------- 2 files changed, 66 insertions(+), 49 deletions(-) diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 6841f07848..703f1bfd6d 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -154,7 +154,6 @@ static DisplayState display_state; int nographic; int vncviewer; int vncunused; -int vncswitchbpp; const char* keyboard_layout = NULL; int64_t ticks_per_sec; char *boot_device = NULL; @@ -6560,7 +6559,6 @@ void help(void) "-vnc display start a VNC server on display\n" "-vncviewer start a vncviewer process for this domain\n" "-vncunused bind the VNC server to an unused port\n" - "-vnc-switch-bpp VNC server closes connections when the guest OS changes colour depth\n" #ifndef NO_DAEMONIZE "-daemonize daemonize QEMU after initializing\n" #endif @@ -6662,7 +6660,6 @@ enum { QEMU_OPTION_acpi, QEMU_OPTION_vncviewer, QEMU_OPTION_vncunused, - QEMU_OPTION_vncswitchbpp, QEMU_OPTION_pci, }; @@ -6746,7 +6743,6 @@ const QEMUOption qemu_options[] = { { "vnc", HAS_ARG, QEMU_OPTION_vnc }, { "vncviewer", 0, QEMU_OPTION_vncviewer }, { "vncunused", 0, QEMU_OPTION_vncunused }, - { "vnc-switch-bpp", 0, QEMU_OPTION_vncswitchbpp }, /* temporary options */ { "usb", 0, QEMU_OPTION_usb }, @@ -7164,7 +7160,6 @@ int main(int argc, char **argv) nographic = 0; vncviewer = 0; vncunused = 0; - vncswitchbpp = 0; kernel_filename = NULL; kernel_cmdline = ""; #ifndef CONFIG_DM @@ -7595,9 +7590,6 @@ int main(int argc, char **argv) case QEMU_OPTION_vncunused: vncunused++; break; - case QEMU_OPTION_vncswitchbpp: - vncswitchbpp++; - break; case QEMU_OPTION_pci: direct_pci = optarg; break; @@ -7830,7 +7822,6 @@ int main(int argc, char **argv) } else if (vnc_display != NULL || vncunused != 0) { int vnc_display_port; char password[20]; - ds->switchbpp = vncswitchbpp; vnc_display_init(ds); xenstore_read_vncpasswd(domid, password, sizeof(password)); vnc_display_password(ds, password); diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index f07ce8ca34..7f87f8ed18 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -157,6 +157,7 @@ struct VncState int has_resize; int has_hextile; int has_pointer_type_change; + int has_WMVi; int absolute; int last_x; int last_y; @@ -1310,6 +1311,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) vs->has_hextile = 0; vs->has_resize = 0; vs->has_pointer_type_change = 0; + vs->has_WMVi = 0; vs->absolute = -1; vs->ds->dpy_copy = NULL; @@ -1330,6 +1332,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) case -257: vs->has_pointer_type_change = 1; break; + case 0x574D5669: + vs->has_WMVi = 1; default: break; } @@ -1410,6 +1414,57 @@ static void set_pixel_format(VncState *vs, vga_hw_update(); } +static void pixel_format_message (VncState *vs) { + char pad[3] = { 0, 0, 0 }; + + vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */ + if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */ + else vnc_write_u8(vs, vs->depth * 8); /* depth */ + +#ifdef WORDS_BIGENDIAN + vnc_write_u8(vs, 1); /* big-endian-flag */ +#else + vnc_write_u8(vs, 0); /* big-endian-flag */ +#endif + vnc_write_u8(vs, 1); /* true-color-flag */ + if (vs->depth == 4) { + vnc_write_u16(vs, 0xFF); /* red-max */ + vnc_write_u16(vs, 0xFF); /* green-max */ + vnc_write_u16(vs, 0xFF); /* blue-max */ + vnc_write_u8(vs, 16); /* red-shift */ + vnc_write_u8(vs, 8); /* green-shift */ + vnc_write_u8(vs, 0); /* blue-shift */ + vs->send_hextile_tile = send_hextile_tile_32; + } else if (vs->depth == 2) { + vnc_write_u16(vs, 31); /* red-max */ + vnc_write_u16(vs, 63); /* green-max */ + vnc_write_u16(vs, 31); /* blue-max */ + vnc_write_u8(vs, 11); /* red-shift */ + vnc_write_u8(vs, 5); /* green-shift */ + vnc_write_u8(vs, 0); /* blue-shift */ + vs->send_hextile_tile = send_hextile_tile_16; + } else if (vs->depth == 1) { + /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */ + vnc_write_u16(vs, 7); /* red-max */ + vnc_write_u16(vs, 7); /* green-max */ + vnc_write_u16(vs, 3); /* blue-max */ + vnc_write_u8(vs, 5); /* red-shift */ + vnc_write_u8(vs, 2); /* green-shift */ + vnc_write_u8(vs, 0); /* blue-shift */ + vs->send_hextile_tile = send_hextile_tile_8; + } + vs->red_max = vs->red_max1; + vs->green_max = vs->green_max1; + vs->blue_max = vs->blue_max1; + vs->red_shift = vs->red_shift1; + vs->green_shift = vs->green_shift1; + vs->blue_shift = vs->blue_shift1; + vs->pix_bpp = vs->depth * 8; + vs->write_pixels = vnc_write_pixels_copy; + + vnc_write(vs, pad, 3); /* padding */ +} + static void vnc_dpy_colourdepth(DisplayState *ds, int depth) { int host_big_endian_flag; @@ -1457,6 +1512,14 @@ static void vnc_dpy_colourdepth(DisplayState *ds, int depth) } if (ds->switchbpp) { vnc_client_error(vs); + } else if (vs->csock != -1 && vs->has_WMVi) { + /* Sending a WMVi message to notify the client*/ + vnc_write_u8(vs, 0); /* msg id */ + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); /* number of rects */ + vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669); + pixel_format_message(vs); + vnc_flush(vs); } else { if (vs->pix_bpp == 4 && vs->depth == 4 && host_big_endian_flag == vs->pix_big_endian && @@ -1578,7 +1641,6 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) { size_t l; - char pad[3] = { 0, 0, 0 }; vga_hw_update(); @@ -1587,45 +1649,7 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) vnc_write_u16(vs, vs->ds->width); vnc_write_u16(vs, vs->ds->height); - vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */ - if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */ - else vnc_write_u8(vs, vs->depth * 8); /* depth */ - -#ifdef WORDS_BIGENDIAN - vnc_write_u8(vs, 1); /* big-endian-flag */ -#else - vnc_write_u8(vs, 0); /* big-endian-flag */ -#endif - vnc_write_u8(vs, 1); /* true-color-flag */ - if (vs->depth == 4) { - vnc_write_u16(vs, 0xFF); /* red-max */ - vnc_write_u16(vs, 0xFF); /* green-max */ - vnc_write_u16(vs, 0xFF); /* blue-max */ - vnc_write_u8(vs, 16); /* red-shift */ - vnc_write_u8(vs, 8); /* green-shift */ - vnc_write_u8(vs, 0); /* blue-shift */ - vs->send_hextile_tile = send_hextile_tile_32; - } else if (vs->depth == 2) { - vnc_write_u16(vs, 31); /* red-max */ - vnc_write_u16(vs, 63); /* green-max */ - vnc_write_u16(vs, 31); /* blue-max */ - vnc_write_u8(vs, 11); /* red-shift */ - vnc_write_u8(vs, 5); /* green-shift */ - vnc_write_u8(vs, 0); /* blue-shift */ - vs->send_hextile_tile = send_hextile_tile_16; - } else if (vs->depth == 1) { - /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */ - vnc_write_u16(vs, 7); /* red-max */ - vnc_write_u16(vs, 7); /* green-max */ - vnc_write_u16(vs, 3); /* blue-max */ - vnc_write_u8(vs, 5); /* red-shift */ - vnc_write_u8(vs, 2); /* green-shift */ - vnc_write_u8(vs, 0); /* blue-shift */ - vs->send_hextile_tile = send_hextile_tile_8; - } - vs->write_pixels = vnc_write_pixels_copy; - - vnc_write(vs, pad, 3); /* padding */ + pixel_format_message(vs); l = strlen(domain_name); vnc_write_u32(vs, l); @@ -2436,6 +2460,8 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) options++; if (strncmp(options, "password", 8) == 0) { password = 1; /* Require password auth */ + } else if (strncmp(options, "switchbpp", 9) == 0) { + ds->switchbpp = 1; #if CONFIG_VNC_TLS } else if (strncmp(options, "tls", 3) == 0) { tls = 1; /* Require TLS */ -- 2.30.2